import random
from info.libs.yuntongxun.sms import CCP
from . import passport_blue
from flask import render_template, request, jsonify, session, current_app, g, redirect, make_response
from info.utils.response_code import RET
from info.models import User
from info import db, redis_store, constants
from info.utils.commons import login_required
from info.utils.captcha.captcha import captcha
import re


# 实现登陆
@passport_blue.route('/api/v1.0/session', methods=['POST', 'DELETE'])
def user_login():
    if request.method == 'DELETE':
        session.pop('user_id', None)
        session.pop('name', None)
        session.pop('mobile', None)
        return jsonify(errno=RET.OK, errmsg='OK')
    # 用户登录
    # 1、获取参数，mobile，password
    mobile = request.json.get('mobile')
    password = request.json.get('password')
    # 2、检查参数的完整性
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 3、检查手机号格式
    if not re.match(r'1[3456789]\d{9}$', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
    # 4、根据手机号查询用户，确认用户已注册
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询用户失败')
    # 5、校验密码是否正确
    if not user or not user.check_password(password):
        return jsonify(errno=RET.PWDERR, errmsg='用户名或密码错误')
    # 7、提交数据到mysql
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 8、实现状态保持，缓存用户信息
    session['user_id'] = user.id
    session['mobile'] = user.mobile
    session['name'] = user.name
    # session['nick_name'] = user.nick_name
    # 9、返回结果
    return jsonify(errno=RET.OK, errmsg='登陆成功')


# 获取登陆状态
@passport_blue.route('/api/v1.0/session')
@login_required
def check_user_login():
    user = g.user
    if user:
        data = {
            'name': user.name,
            'user_id': user.id
        }
        return jsonify(errno=RET.OK, errmsg='OK', data=data)
    return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')


# 获取图片验证码接口
@passport_blue.route("/api/v1.0/imagecode")
def imagecode():
    # 获取前端的UUID参数
    imageCodeId = request.args.get("cur")
    # 如果UUID不存在，返回信息
    if not imageCodeId:
        return jsonify(errno=RET.PARAMERR, errmsg="获取UUid失败")
    # 生成图片验证码
    name, text, image = captcha.generate_captcha()
    try:
        redis_store.setex("cur" + imageCodeId, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="缓存图片验证码失败")
    else:
        resp = make_response(image)
        resp.headers["Content_Type"] = "image/jpg"
        return resp


# 发送短信接口
@passport_blue.route("/api/v1.0/smscode", methods=["POST"])
def send_smscode():
    # 获取前端的手机号，图片验证码，和UUID
    mobile = request.json.get("mobile")
    image_code = request.json.get("image_code")
    image_code_id = request.json.get("image_code_id")
    # 检验参数是否完整
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")
    # 检验手机号格式是否正确
    if not re.match("1[3-9]\d{9}$", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号码格式错误")
    try:
        real_image_code_id = redis_store.get("cur" + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="图片验证码读取失败")
    if not real_image_code_id:
        return jsonify(errno=RET.NODATA, errmsg="图片验证码过期")
    try:
        redis_store.delete("cur" + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
    if real_image_code_id.lower() != image_code.lower():
        return jsonify(errno=RET.PARAMERR, errmsg="验证码输入错误")
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询用户失败")
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg="用户已注册")

    # 生成随机验证码
    smscode = "%06d" % random.randint(0, 999999)
    try:
        redis_store.setex("smscode:" + mobile, constants.IMAGE_CODE_REDIS_EXPIRES, smscode)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="短信验证码存储失败")
    try:
        ccp = CCP()
        result = ccp.send_template_sms(mobile, [smscode, 5], 1)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg="第三方错误")
    if result == 0:
        return jsonify(errno=RET.OK, errmsg="短信验证码发送成功")
    else:
        return jsonify(errno=RET.OK, errmsg="短信验证码发送失败")


# 用户注册接口
@passport_blue.route("/api/v1.0/user", methods=["POST"])
def register():
    # 获取前端参数
    mobile = request.json.get("mobile")
    phonecode = request.json.get("phonecode")
    password = request.json.get("password")
    # 判断参数是否完整
    if not all([mobile, phonecode, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数缺失")
    # 判断手机号码格式
    if not re.match("1[3-9]\d{9}$", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号码格式错误")
    # 从redis中获取真实的短信验证码
    try:
        real_phonecode = redis_store.get("smscode:" + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="短信验证码数据库读取错误")
    if not real_phonecode:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码过期")
    if real_phonecode != str(phonecode):
        return jsonify(errno=RET.PARAMERR, errmsg="短信验证码输入错误")
    try:
        redis_store.delete("smscode:" + mobile)
    except Exception as e:
        current_app.logger.error(e)
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmesg="用户数据查询失败")
    else:
        if user is not None:
            return jsonify(errno=RET.DATAEXIST, errmesg="手机号码已注册")
    # 保存注册信息到mysql
    user = User()
    # password_hash=user.password(password)
    # user.password_hash=password_hash
    user.password = password
    user.mobile = mobile
    user.name = mobile

    # 提交注册信息
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存用户注册信息失败")
    # 缓存注册信息到redis
    session['user_id'] = user.id
    session['mobile'] = user.mobile
    session['name'] = user.name
    return jsonify(errno=RET.OK, errmsg="注册成功")

@passport_blue.route("/favicon.ico")
def favicon():
    """
    项目首页加载完成后，首先实现favicon图标的加载:
    1、浏览器会默认访问favicon图标，访问的路径：
    http://127.0.0.1:5000/favicon.ico
    2、项目中favicon文件存储的路径：
    static/news/favicon.ico
    3、使用蓝图定义路由
    /favicon.ico
    4、把/news/favicon.ico文件发给浏览器

    代码实现后，浏览器加载不到favicon图标的解决方法：
    1、清除浏览器缓存
    2、清除浏览器的浏览器记录，
    3、退出浏览器，彻底退出。

    """
    # send_static_file函数是flask框架自带的函数，作用是把具体的文件发送给浏览器。
    return current_app.send_static_file('favicon.ico')